# 多线程
from lxml import etree
from queue import Queue
import threading
import requests


class QiuBaiSpider(object):
    def __init__(self):
        self.temp_url = "https://www.qiushibaike.com/text/page/{}/"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
        }

        # 准备队列 存储：url 响应内容  数据内容
        self.url_queue = Queue()
        self.response_queue = Queue()
        self.data_queue = Queue()

    def get_url_list(self):
        """
        准备13页 url地址的方法
        :return: url地址的列表
        """
        for i in range(1, 14):
            # 将生成的url地址放到 url队列中
            self.url_queue.put(self.temp_url.format(i))

    def send_request(self):
        """
        发送请求获取响应的方法
        :param url: 发送请求的url地址
        :return:
        """
        while True:
            url = self.url_queue.get()
            print(f"正在抓取-----{url}")
            response = requests.get(url, headers=self.headers)
            # 将响应内容 放入 响应队列中
            self.response_queue.put(response.content.decode())
            # url队列计数-1
            self.url_queue.task_done()

    def parse_data(self):
        """
        数据解析的方法
        :param html_str: 响应的网页源代码
        :return:
        """
        while True:
            # 从响应队列中取出响应数据
            html_str = self.response_queue.get()
            # 将html字符串 转换成element对象
            html = etree.HTML(html_str)
            # 对数据进行分组
            div_list = html.xpath("//div[@class='col1 old-style-col1']/div")
            # 准备保存数据的列表
            content_list = []
            for div in div_list:
                item = {}
                item["username"] = div.xpath(".//h2/text()")[0].strip()
                content_list.append(item)

            # 将提取到的数据放入 数据队列中
            self.data_queue.put(content_list)
            # 将 响应队列的计数-1
            self.response_queue.task_done()

    def save_data(self):
        """
        保存数据的方法
        :param content_list: 数据列表
        :return:
        """
        while True:
            content_list = self.data_queue.get()
            for content in content_list:
                print(content)
            # 数据队列计数-1
            self.data_queue.task_done()

    def run(self):
        # 1. 准备url地址
        t_list = []
        # 创建线程
        t_url = threading.Thread(target=self.get_url_list)
        t_list.append(t_url)
        # 2. 遍历 url列表 获取每一个url地址 进行发送请求获取响应
        t_parse = threading.Thread(target=self.send_request)
        t_list.append(t_parse)
        t_content = threading.Thread(target=self.parse_data)
        t_list.append(t_content)
        t_save = threading.Thread(target=self.save_data)
        t_list.append(t_save)

        for t in t_list:
            # 守护线程
            t.setDaemon(True)
            # 线程启动
            t.start()

        for q in [self.url_queue, self.response_queue, self.data_queue]:
            # 队列中维持了一个计数,计数不为0时候让主线程阻塞等待,队列计数为0的时候才会继续往后执行
            q.join()    # 阻塞等待

        print("主线程结束.......")


if __name__ == '__main__':
    qiubai = QiuBaiSpider()
    qiubai.run()
